﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using TextBoxWKeyBoard;

namespace NewTextBoxKeyBoard
{
    public class TextBoxKeyBoard : Panel
    {
        private Button btn_Pic;
        internal HsTextBox txt_Input;

        public int MaxLength
        {
            get
            {
                return txt_Input.MaxLength;
            }
            set
            {
                txt_Input.MaxLength = value;
            }
        }

        public EntryMode EntryMode
        {
            get
            {
                return txt_Input.EntryMode;
            }
            set
            {
                txt_Input.EntryMode = value;
            }
        }

        public TextBoxKeyBoard()
        {
            DrawLeft();
            DrawRight();
        }

        private void DrawLeft()
        {
            txt_Input = new HsTextBox(EntryMode.Standard);
            txt_Input.Parent = this;
            txt_Input.AutoSize = false;
            txt_Input.Dock = DockStyle.Fill;
        }

        private void DrawRight()
        {
            btn_Pic = new Button();
            btn_Pic.BackgroundImage = Properties.Resources.KeyBoard;
            btn_Pic.BackgroundImageLayout = ImageLayout.Stretch;
            btn_Pic.Parent = this;
            btn_Pic.Width = 60;
            btn_Pic.Dock = DockStyle.Right;
            btn_Pic.Click += delegate(object sender, EventArgs e)
            {
                txt_Input.Show();
                txt_Input.Focus();
            };
        }
    }

    internal partial class HsTextBox : TextBox
    {
        [DllImport("User32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hwnd);

        private EntryMode _entryMode = EntryMode.Standard;

        public EntryMode EntryMode
        {
            get
            {
                return _entryMode;
            }
            set
            {
                if (value != _entryMode)
                {
                    _entryMode = value;

                    DrawDropPanel();
                }
            }
        }

        private BaseKeyBoardForm keyBoard;
        private HsToolStripDropDown toolStripDropDown;
        private ToolStripControlHost toolStripControlHost;

        public HsTextBox()
            : this(EntryMode.Standard)
        {
            InitializeComponent();
        }

        public HsTextBox(EntryMode entryMode)
        {
            InitializeComponent();

            EntryMode = entryMode;
            DrawDropPanel();
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.CloseDropPanel();
                return;
            }
            if (EntryMode == EntryMode.Numeric)
            {
                CalText(e.KeyCode);

                if (CheckIfNumericKey(e.KeyCode, this.Text.Contains(".")) == false)
                {
                    e.SuppressKeyPress = true;
                }
            }
            this.SelectionStart = this.Text.Length;
            base.OnKeyDown(e);
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if (char.IsLower(e.KeyChar))
            {
                e.KeyChar = char.ToUpperInvariant(e.KeyChar);
            }
            base.OnKeyPress(e);
        }

        private bool CheckIfNumericKey(Keys K, bool isDecimalPoint)
        {
            if (K == Keys.Back)
            {
                return true;
            }
            else
            {
                if (K == Keys.OemPeriod || K == Keys.Decimal)
                {
                    return isDecimalPoint ? false : true;
                }
                else
                {
                    if ((K >= Keys.D0) && (K <= Keys.D9))
                    {
                        return true;
                    }
                    else
                    {
                        if ((K >= Keys.NumPad0) && (K <= Keys.NumPad9))
                        {
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }
                }
            }
        }

        private void CalText(Keys inputKey)
        {
            var content = this.Text;
            var result = decimal.MinusOne;
            if (decimal.TryParse(content, out result))
            {
                switch (inputKey)
                {
                    case Keys.Add:
                        result += 1;
                        break;

                    case Keys.OemMinus:
                        if (result > 0)
                        {
                            result -= 1;
                        }
                        break;
                }
            }
            content = result.ToString();
            if (content.Length <= this.MaxLength && result >= 0)
            {
                this.Text = content;
            }
        }

        /// <summary>
        /// 关闭下拉面板
        /// </summary>
        public void CloseDropPanel()
        {
            toolStripDropDown.Close(ToolStripDropDownCloseReason.CloseCalled);
        }

        public new void Show()
        {
            if (toolStripDropDown == null)
            {
                return;
            }
            Point location = this.PointToScreen(this.Location);
            if (location.Y > (Screen.PrimaryScreen.WorkingArea.Height - keyBoard.Height - this.Height))
            {
                toolStripDropDown.Show(this, new Point(5, -5), ToolStripDropDownDirection.AboveLeft | ToolStripDropDownDirection.AboveRight);
            }
            else
            {
                toolStripDropDown.Show(this, new Point(0, this.Height), ToolStripDropDownDirection.Default);
            }
            SetForegroundWindow(keyBoard.Handle);
        }

        /// <summary>
        /// 设置下拉Panel
        /// </summary>
        private void DrawDropPanel()
        {
            Action<System.ComponentModel.Component> dispose = new Action<System.ComponentModel.Component>((control) =>
            {
                if (control != null)
                {
                    control.Dispose();
                    control = null;
                }
            });
            dispose(keyBoard);
            keyBoard = EntryMode == EntryMode.Standard ? new HoverKeyboard() : (BaseKeyBoardForm)new HoverNumPad();
            keyBoard.textBox = this;
            keyBoard.TopLevel = false;
            keyBoard.Dock = DockStyle.Fill;
            keyBoard.Show();

            dispose(toolStripDropDown);
            dispose(toolStripControlHost);
            toolStripControlHost = new ToolStripControlHost(keyBoard);
            toolStripDropDown = new HsToolStripDropDown();

            toolStripControlHost.Margin = Padding.Empty;
            toolStripControlHost.Padding = Padding.Empty;
            toolStripControlHost.AutoSize = false;

            toolStripDropDown.Padding = Padding.Empty;
            toolStripDropDown.Items.Add(toolStripControlHost);
        }
    }

    /// <summary>
    /// 重写ToolStripDropDown 使用双缓存减少闪烁
    /// </summary>
    internal class HsToolStripDropDown : ToolStripDropDown
    {
        protected override CreateParams CreateParams
        {
            get
            {
                var cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }
    }

    public enum EntryMode
    {
        Standard,
        Numeric
    }
}